/**
 * 安全监控中间件
 * EndoSight-UC 医疗AI系统 - P0级安全修复
 *
 * 监控安全相关事件，检测异常行为，提供安全审计
 */

import winston from 'winston';
import { getSecurityStatus } from '../config/security.js';

const logger = winston.createLogger({
  level: 'info',
  format: winston.format.combine(
    winston.format.timestamp(),
    winston.format.json()
  ),
  transports: [
    new winston.transports.Console({
      format: winston.format.simple()
    }),
    new winston.transports.File({
      filename: 'logs/security.log',
      level: 'warn'
    })
  ]
});

// 安全事件计数器
const securityMetrics = {
  totalRequests: 0,
  failedLogins: 0,
  suspiciousRequests: 0,
  blockedRequests: 0,
  lastReset: new Date()
};

// 失败登录尝试跟踪（IP级别）
const failedLoginAttempts = new Map();

// 可疑IP黑名单
const suspiciousIPs = new Set();

// 安全事件记录
const securityEvents = [];

/**
 * 安全监控中间件
 */
export const securityMonitor = (req, res, next) => {
  const startTime = Date.now();
  const clientIP = req.ip || req.connection.remoteAddress;

  // 增强请求统计
  securityMetrics.totalRequests++;

  // 记录请求基本信息
  const requestInfo = {
    ip: clientIP,
    method: req.method,
    url: req.url,
    userAgent: req.get('User-Agent'),
    timestamp: new Date().toISOString(),
    userId: req.user?.doctor_id || 'anonymous'
  };

  // 检测可疑行为
  const suspiciousActivity = detectSuspiciousActivity(req, clientIP);

  if (suspiciousActivity) {
    handleSuspiciousActivity(req, suspiciousActivity);
    securityMetrics.suspiciousRequests++;
  }

  // 监控响应
  const originalSend = res.send;
  res.send = function(data) {
    const endTime = Date.now();
    const responseTime = endTime - startTime;

    // 记录响应信息
    const responseInfo = {
      ...requestInfo,
      statusCode: res.statusCode,
      responseTime: responseTime,
      contentLength: res.get('Content-Length') || 0
    };

    // 检测异常响应
    if (res.statusCode >= 400) {
      handleErrorResponse(req, res, responseInfo);
    }

    // 记录安全事件
    if (shouldLogSecurityEvent(req, res, suspiciousActivity)) {
      logSecurityEvent('HTTP_REQUEST', responseInfo, suspiciousActivity);
    }

    return originalSend.call(this, data);
  };

  next();
};

/**
 * 登录安全监控
 */
export const loginSecurityMonitor = (req, res, next) => {
  const clientIP = req.ip || req.connection.remoteAddress;
  const originalSend = res.send;

  res.send = function(data) {
    const responseData = typeof data === 'string' ? JSON.parse(data) : data;

    // 检测登录失败
    if (res.statusCode === 401 || (responseData && responseData.success === false)) {
      handleFailedLogin(clientIP, req.body?.username, req.body);
      securityMetrics.failedLogins++;
    }

    // 检测登录成功
    if (responseData && responseData.success === true && responseData.data?.token) {
      handleSuccessfulLogin(clientIP, req.body?.username, responseData.data);
    }

    return originalSend.call(this, data);
  };

  next();
};

/**
 * 检测可疑活动
 */
const detectSuspiciousActivity = (req, ip) => {
  const suspicious = [];

  // 检测可疑User-Agent
  const userAgent = req.get('User-Agent') || '';
  if (userAgent.length < 10 || userAgent.includes('curl') || userAgent.includes('wget')) {
    suspicious.push({
      type: 'SUSPICIOUS_USER_AGENT',
      description: '检测到可疑的User-Agent',
      details: { userAgent }
    });
  }

  // 检测异常请求头
  const forwardedFor = req.get('X-Forwarded-For');
  if (forwardedFor && forwardedFor.split(',').length > 3) {
    suspicious.push({
      type: 'EXCESSIVE_PROXY_HOPS',
      description: '检测到过多的代理跳转',
      details: { forwardedFor }
    });
  }

  // 检测已知的可疑IP
  if (suspiciousIPs.has(ip)) {
    suspicious.push({
      type: 'KNOWN_SUSPICIOUS_IP',
      description: '检测到已知的可疑IP地址',
      details: { ip }
    });
  }

  // 检测异常请求路径
  const suspiciousPaths = ['/admin', '/config', '/env', '/.env', '/git'];
  if (suspiciousPaths.some(path => req.url.toLowerCase().includes(path))) {
    suspicious.push({
      type: 'SUSPICIOUS_PATH',
      description: '检测到对敏感路径的访问尝试',
      details: { path: req.url }
    });
  }

  return suspicious.length > 0 ? suspicious : null;
};

/**
 * 处理可疑活动
 */
const handleSuspiciousActivity = (req, suspiciousActivity) => {
  const clientIP = req.ip || req.connection.remoteAddress;

  // 记录可疑活动
  logSecurityEvent('SUSPICIOUS_ACTIVITY', {
    ip: clientIP,
    method: req.method,
    url: req.url,
    userAgent: req.get('User-Agent'),
    suspicious: suspiciousActivity
  });

  // 根据严重程度决定是否阻止
  const severity = calculateThreatSeverity(suspiciousActivity);

  if (severity >= 7) {
    // 高威胁：暂时阻止IP
    blockIP(clientIP, 3600000); // 阻止1小时
    securityMetrics.blockedRequests++;
  } else if (severity >= 5) {
    // 中等威胁：标记为可疑IP
    suspiciousIPs.add(clientIP);
  }
};

/**
 * 处理登录失败
 */
const handleFailedLogin = (ip, username, requestBody) => {
  const attemptKey = `${ip}:${username || 'unknown'}`;
  const currentAttempts = failedLoginAttempts.get(attemptKey) || {
    count: 0,
    firstAttempt: new Date(),
    lastAttempt: new Date()
  };

  currentAttempts.count++;
  currentAttempts.lastAttempt = new Date();
  failedLoginAttempts.set(attemptKey, currentAttempts);

  // 检测暴力破解尝试
  if (currentAttempts.count >= 5) {
    const timeWindow = currentAttempts.lastAttempt - currentAttempts.firstAttempt;

    if (timeWindow < 300000) { // 5分钟内超过5次失败
      logSecurityEvent('BRUTE_FORCE_DETECTED', {
        ip: ip,
        username: username,
        attempts: currentAttempts.count,
        timeWindow: timeWindow
      });

      // 临时阻止IP
      blockIP(ip, 1800000); // 阻止30分钟
      securityMetrics.blockedRequests++;
    }
  }

  // 记录失败登录
  logSecurityEvent('LOGIN_FAILED', {
    ip: ip,
    username: username,
    attemptCount: currentAttempts.count,
    requestBody: {
      username: requestBody?.username,
      // 不记录密码
    }
  });
};

/**
 * 处理成功登录
 */
const handleSuccessfulLogin = (ip, username, responseData) => {
  // 清除失败登录记录
  const attemptKey = `${ip}:${username || 'unknown'}`;
  failedLoginAttempts.delete(attemptKey);

  // 从可疑IP列表中移除（如果存在）
  if (suspiciousIPs.has(ip)) {
    suspiciousIPs.delete(ip);
  }

  // 记录成功登录
  logSecurityEvent('LOGIN_SUCCESS', {
    ip: ip,
    username: username,
    userId: responseData.doctor?.doctor_id,
    role: responseData.doctor?.role
  });
};

/**
 * 处理错误响应
 */
const handleErrorResponse = (req, res, responseInfo) => {
  // 检测敏感信息泄露
  const errorData = res.locals.error || {};
  if (errorData.stack || errorData.sql) {
    logSecurityEvent('SENSITIVE_INFO_LEAK', {
      ip: responseInfo.ip,
      url: responseInfo.url,
      statusCode: responseInfo.statusCode,
      hasStack: !!errorData.stack,
      hasSQL: !!errorData.sql
    });
  }
};

/**
 * 计算威胁严重程度
 */
const calculateThreatSeverity = (suspiciousActivity) => {
  let severity = 0;

  suspiciousActivity.forEach(activity => {
    switch (activity.type) {
      case 'KNOWN_SUSPICIOUS_IP':
        severity += 8;
        break;
      case 'SUSPICIOUS_PATH':
        severity += 6;
        break;
      case 'EXCESSIVE_PROXY_HOPS':
        severity += 4;
        break;
      case 'SUSPICIOUS_USER_AGENT':
        severity += 2;
        break;
    }
  });

  return Math.min(severity, 10); // 最大值为10
};

/**
 * 阻止IP地址
 */
const blockIP = (ip, duration) => {
  suspiciousIPs.add(ip);

  logSecurityEvent('IP_BLOCKED', {
    ip: ip,
    duration: duration,
    blockTime: new Date().toISOString(),
    unblockTime: new Date(Date.now() + duration).toISOString()
  });

  // 设置自动解除阻止
  setTimeout(() => {
    suspiciousIPs.delete(ip);
    logSecurityEvent('IP_UNBLOCKED', {
      ip: ip,
      unblockTime: new Date().toISOString()
    });
  }, duration);
};

/**
 * 记录安全事件
 */
const logSecurityEvent = (eventType, details, additionalInfo = null) => {
  const event = {
    eventType,
    timestamp: new Date().toISOString(),
    details,
    additionalInfo
  };

  // 存储事件（最近1000个）
  securityEvents.push(event);
  if (securityEvents.length > 1000) {
    securityEvents.shift();
  }

  // 根据事件类型选择日志级别
  let logLevel = 'info';
  if (eventType.includes('DETECTED') || eventType.includes('BLOCKED')) {
    logLevel = 'warn';
  } else if (eventType.includes('LEAK') || eventType.includes('BRUTE_FORCE')) {
    logLevel = 'error';
  }

  logger[logLevel](`🔒 Security Event [${eventType}]:`, event);
};

/**
 * 判断是否应该记录安全事件
 */
const shouldLogSecurityEvent = (req, res, suspiciousActivity) => {
  // 总是记录可疑活动
  if (suspiciousActivity) return true;

  // 记录错误响应
  if (res.statusCode >= 400) return true;

  // 记录认证相关的请求
  if (req.url.includes('/auth/') || req.url.includes('/login')) return true;

  // 记录管理相关的请求
  if (req.url.includes('/admin') || req.url.includes('/manage')) return true;

  return false;
};

/**
 * 获取安全状态报告
 */
export const getSecurityReport = () => {
  const uptime = Date.now() - securityMetrics.lastReset.getTime();

  return {
    timestamp: new Date().toISOString(),
    uptime_ms: uptime,
    metrics: securityMetrics,
    status: getSecurityStatus(),
    currentThreats: {
      suspiciousIPs: Array.from(suspiciousIPs),
      failedLoginAttempts: Array.from(failedLoginAttempts.entries()).map(([key, data]) => ({
        key,
        ...data
      }))
    },
    recentEvents: securityEvents.slice(-50), // 最近50个事件
    recommendations: generateSecurityRecommendations()
  };
};

/**
 * 生成安全建议
 */
const generateSecurityRecommendations = () => {
  const recommendations = [];

  if (securityMetrics.failedLogins > securityMetrics.totalRequests * 0.1) {
    recommendations.push({
      priority: 'HIGH',
      type: 'AUTHENTICATION',
      message: '登录失败率过高，建议加强身份验证措施'
    });
  }

  if (securityMetrics.suspiciousRequests > securityMetrics.totalRequests * 0.05) {
    recommendations.push({
      priority: 'MEDIUM',
      type: 'MONITORING',
      message: '可疑请求较多，建议审查访问日志'
    });
  }

  if (suspiciousIPs.size > 10) {
    recommendations.push({
      priority: 'MEDIUM',
      type: 'ACCESS_CONTROL',
      message: '可疑IP数量较多，建议实施更严格的访问控制'
    });
  }

  return recommendations;
};

/**
 * 重置安全统计
 */
export const resetSecurityMetrics = () => {
  securityMetrics.totalRequests = 0;
  securityMetrics.failedLogins = 0;
  securityMetrics.suspiciousRequests = 0;
  securityMetrics.blockedRequests = 0;
  securityMetrics.lastReset = new Date();

  // 清理过期的失败登录记录
  const now = Date.now();
  for (const [key, data] of failedLoginAttempts.entries()) {
    if (now - data.lastAttempt > 3600000) { // 1小时前的记录
      failedLoginAttempts.delete(key);
    }
  }

  logger.info('📊 安全统计已重置');
};

export default {
  securityMonitor,
  loginSecurityMonitor,
  getSecurityReport,
  resetSecurityMetrics
};